package com.flyxiaozhu.erp.core.utils;

import java.util.*;

public class CollectionUtils {
    /**
     * 查找列表里面某值的位置
     *
     * @param collection 列表
     * @param filter     比较方法
     * @param <T>        对象
     * @return int
     */
    public static <T> int indexOf(Collection<T> collection, Filter<T> filter) {
        Iterator<T> i$ = collection.iterator();

        int i = 0;
        while (i$.hasNext()) {
            if (filter.filter(i$.next())) {
                return i;
            }
            i++;
        }
        return -1;
    }

    /**
     * 查找列表里面是否含有某值
     *
     * @param collection 列表
     * @param filter     比较方法
     * @param <T>        对象
     * @return boolean
     */
    public static <T> boolean has(Collection<T> collection, Filter<T> filter) {
        for (T o : collection) {
            if (filter.filter(o)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 查找数组里面某值的位置
     *
     * @param collection 数组
     * @param filter     比较方法
     * @param <T>        对象
     * @return int
     */
    public static <T> int indexOf(T[] collection, Filter<T> filter) {
        int i = 0;
        while (i < collection.length) {
            if (filter.filter(collection[i])) {
                return i;
            }
            i++;
        }
        return -1;
    }

    /**
     * 查找列表里面是否含有某值
     *
     * @param collection 数组
     * @param filter     比较方法
     * @param <T>        对象
     * @return boolean
     */
    public static <T> boolean has(T[] collection, Filter<T> filter) {
        int i = 0;
        while (i < collection.length) {
            if (filter.filter(collection[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将列表每一项经过处理后生成新的列表
     *
     * @param collection 列表
     * @param mapper     处理方法
     * @param <T>        旧对象
     * @param <H>        新对象
     * @return List<KeyType>
     */
    public static <T, H> List<H> map(Collection<T> collection, Mapper<T, H> mapper) {
        List<H> result = new ArrayList<>();
        for (T o : collection) {
            result.add(mapper.map(o));
        }

        return result;
    }

    /**
     * 将数组每一项经过处理后生成新的列表
     *
     * @param collection 数组
     * @param mapper     处理方法
     * @param <T>        旧对象
     * @param <H>        新对象
     * @return List<KeyType>
     */
    public static <T, H> List<H> map(T[] collection, Mapper<T, H> mapper) {
        List<H> result = new ArrayList<>();
        for (T o : collection) {
            result.add(mapper.map(o));
        }

        return result;
    }

    /**
     * 列表每一项进行判断，只要其中某一项判断成功返回true
     *
     * @param collection 列表
     * @param filter     判定方法
     * @param <T>        对象
     * @return boolean
     */
    public static <T> boolean every(Collection<T> collection, Filter<T> filter) {
        for (T o : collection) {
            if (filter.filter(o)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 数组每一项进行判断，只要其中某一项判断成功返回true
     *
     * @param collection 数组
     * @param filter     判定方法
     * @param <T>        对象
     * @return boolean
     */
    public static <T> boolean every(T[] collection, Filter<T> filter) {
        for (T o : collection) {
            if (filter.filter(o)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 列表取项的某个字段作为key生成新的map，返回原数据类型
     *
     * @param collection 列表
     * @param filter     取字段方法
     * @param <T>        对象
     * @param <H>        key的类型
     * @return Map
     */
    public static <T, H> Map<H, T> columnMap(Collection<T> collection, ColumnMapFilter<T, H> filter) {
        Map<H, T> result = new HashMap<>();
        for (T o : collection) {
            result.put(filter.getKey(o), o);
        }

        return result;
    }

    public static <T, H, K> Map<H, K> columnMapFull(Collection<T> collection, ColumnMapFilter2<T, H, K> filter) {
        Map<H, K> result = new HashMap<>();
        for (T o : collection) {
            result.put(filter.getKey(o), filter.getValue(o));
        }

        return result;
    }

    /**
     * 数组取项的某个字段作为key生成新的map
     *
     * @param collection 数组
     * @param filter     取字段方法
     * @param <T>        对象
     * @param <H>        key的类型
     * @return Map
     */
    public static <T, H> Map<H, T> columnMap(T[] collection, ColumnMapFilter<T, H> filter) {
        Map<H, T> result = new HashMap<>();
        for (T o : collection) {
            result.put(filter.getKey(o), o);
        }

        return result;
    }

    public static <T> List<T> filter(Collection<T> collection, Filter<T> filter) {
        List<T> result = new ArrayList<>();
        for (T o : collection) {
            if (filter.filter(o)) {
                result.add(o);
            }
        }

        return result;
    }

    /**
     * 拆分字符串，并将拆分的结果进行处理生成新的对象列表
     *
     * @param commaStr 逗号字符串
     * @param regex    拆分的正则模式
     * @param filter   处理方法
     * @param <T>      新的对象类型
     * @return List<SourceType>
     */
    public static <T> List<T> parseSplitStr(String commaStr, String regex, SplitFilter<T> filter) {
        List<T> result = new ArrayList<>();
        String[] parts = commaStr.split(regex);
        for (String o : parts) {
            if (o.equals("")) {
                continue;
            }
            result.add(filter.filter(o));
        }

        return result;
    }

    public static <SourceType, KeyType, TargetType> Map<KeyType, List<TargetType>> group(List<SourceType> list, GroupFilter<SourceType, KeyType, TargetType> filter) {
        Map<KeyType, List<TargetType>> result = new HashMap<>();

        for (SourceType source : list) {
            if (!result.containsKey(filter.getKey(source))) {
                result.put(filter.getKey(source), new ArrayList<>());
            }

            result.get(filter.getKey(source)).add(filter.getValue(source));
        }

        return result;
    }

    /**
     * 一次性查询根据目标ID查询并生成映射（一对一）
     *
     * @param collection
     * @param filter
     * @param <SourceType>
     * @param <TargetType>
     * @param <TargetType>
     * @return
     */
    public static <SourceType, TargetType, KeyType> Map<KeyType, TargetType> getTargetMapFormList(Collection<SourceType> collection,
                                                                                                  TargetMapFilter<SourceType, TargetType, KeyType> filter) {
        Map<KeyType, TargetType> targetMap = new HashMap<>();
        Set<KeyType> ids = new HashSet<>();
        for (SourceType o : collection) {
            KeyType tid = filter.collectTargetId(o);
            if (tid != null) {
                ids.add(tid);
            }
        }

        List<TargetType> targets = filter.query(ids);

        for (TargetType o : targets) {
            targetMap.put(filter.targetMapKey(o), o);
        }

        for (SourceType o : collection) {
            KeyType key = filter.collectTargetId(o);
            filter.process(o, targetMap.get(key));
        }

        return targetMap;
    }

    /**
     * 一次性查询根据目标ID查询并生成映射（一对多）
     *
     * @param collection
     * @param filter
     * @param <SourceType>
     * @param <TargetType>
     * @param <KeyType>
     * @return
     */
    public static <SourceType, TargetType, KeyType> Map<KeyType, TargetType> getTargetMapFormListForMany(Collection<SourceType> collection,
                                                                                                         TargetMapFilterForMany<SourceType, TargetType, KeyType> filter) {
        Map<KeyType, TargetType> targetMap = new HashMap<>();
        Set<KeyType> ids = new HashSet<>();
        for (SourceType o : collection) {
            Collection<KeyType> tids = filter.collectTargetId(o);
            if (tids != null) {
                ids.addAll(tids);
            }
        }

        List<TargetType> targets = filter.query(ids);

        for (TargetType o : targets) {
            targetMap.put(filter.targetMapKey(o), o);
        }

        for (SourceType o : collection) {
            Collection<KeyType> keyList = filter.collectTargetId(o);
            if (keyList != null) {
                List<TargetType> oList = new ArrayList<>();
                for (KeyType key : keyList) {
                    oList.add(targetMap.get(key));
                }
                filter.process(o, oList);
            } else {
                filter.process(o, new ArrayList<>());
            }
        }

        return targetMap;
    }

    /**
     * 对数据的 vule 进行循环操作
     *
     * @param collection
     * @param result
     * @param filter
     * @param <T>
     * @param <H>
     * @return
     */
    public static <T, H> H reduce(Collection<T> collection, H result, ReduceFilter<T, H> filter) {
        for (T o : collection) {
            result = filter.process(o, result);
        }

        return result;
    }


    public interface SplitFilter<T> {
        T filter(String o);
    }

    public interface ColumnMapFilter<F, H> {
        H getKey(F o);
    }

    public interface ColumnMapFilter2<F, H, T> {
        H getKey(F o);

        T getValue(F o);
    }


    public interface Filter<F> {
        boolean filter(F o);
    }

    public interface Mapper<F, H> {
        H map(F o);
    }

    public interface TargetMapFilter<SourceType, TargetType, KeyType> {
        KeyType collectTargetId(SourceType source);

        List<TargetType> query(Set<KeyType> ids);

        KeyType targetMapKey(TargetType target);

        void process(SourceType source, TargetType target);
    }

    public interface TargetMapFilterForMany<SourceType, TargetType, KeyType> {
        Collection<KeyType> collectTargetId(SourceType source);

        List<TargetType> query(Set<KeyType> ids);

        KeyType targetMapKey(TargetType target);

        void process(SourceType source, List<TargetType> target);
    }

    public interface ReduceFilter<T, H> {
        H process(T target, H result);
    }

    public interface GroupFilter<SourceType, KeyType, TargetType> {
        KeyType getKey(SourceType source);

        TargetType getValue(SourceType source);
    }
}
